package com.spm.librarianmanagersystem.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.dictionary.CoreSynonymDictionary;
import com.hankcs.hanlp.dictionary.CustomDictionary;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
import com.spm.librarianmanagersystem.mapper.BookDetailMapper;
import com.spm.librarianmanagersystem.mapper.BookMapper;
import com.spm.librarianmanagersystem.pojo.Book;
import com.spm.librarianmanagersystem.service.BookInfoService;
import com.spm.librarianmanagersystem.service.BorrowService;
import com.spm.librarianmanagersystem.utils.UserContextHolder;
import com.spm.librarianmanagersystem.vo.BookDetails;
import com.spm.librarianmanagersystem.vo.BookLocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Class: BookInfoServiceImpl
 * @Author: Wu Yue
 * @Time: 16:30 2022/4/4
 * @Description:
 */
@Service("BookInfoService")
public class BookInfoServiceImpl implements BookInfoService {
    @Autowired
    BookDetailMapper bookDetailMapper;

    @Autowired
    BookMapper bookMapper;

    @Autowired
    BorrowService borrowService;

    @Override
    public List<Map<String, String>> searchBookByMessage(BookDetails bookDetails) throws Exception {
        List<Book> books = bookDetailMapper.searchByMessage(bookDetails);


        List<Book> recommendBooks = recommendBooksForUser(UserContextHolder.getCurrentUserId(), books);


        ArrayList<Map<String, String>> booksMap = new ArrayList<>();
        for (Book book : recommendBooks) {
            Map<String, String> map = new HashMap<>();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            map.put("ISBN", book.getISBN());
            map.put("book_name", book.getBookName());
            map.put("publisher", book.getPublisher());
            map.put("published_time", simpleDateFormat.format(book.getPublishedTime()));
            map.put("author", book.getAuthor());
            map.put("cover", book.getCover());
            map.put("category", book.getCategory());
            map.put("score", book.getScore().toString());
            booksMap.add(map);
        }
        return booksMap;
    }

    @Override
    public List<Book> recommendBooksForUser(String userId, List<Book> books) throws Exception {
        List<Book> recommendBooks = null;
        String currentUserId = UserContextHolder.getCurrentUserId();
        JSONArray borrowHistory = borrowService.getBorrowHistory(currentUserId);
        List<String> bookNameList = new ArrayList<>();
        for (int i = 0; i < borrowHistory.size(); i++) {
            bookNameList.add(bookMapper.getABook(borrowHistory.getJSONObject(i).getString("ISBN")).getBookName());
        }
        Map<Book, Double> sortedBooks = new HashMap<>();
        for (Book book : books) {
            double similarityTemp = 0;
            for (String bookName : bookNameList) {
                Vector<String> borrowedBookNamePart = participle(bookName);
                Vector<String> bookNamePart = participle(book.getBookName());
                similarityTemp  += getSimilarity(bookNamePart,borrowedBookNamePart);
            }
            sortedBooks.put(book, similarityTemp);
        }
        List<Book> sortedBookList = sortedBooks.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        return sortedBookList;
    }

    public static Vector<String> participle(String str) {

        Vector<String> str1 = new Vector<String>();//对输入进行分词
        Segment segment = HanLP.newSegment().enableCustomDictionary(true);
        CustomDictionary.add("梁山广");//动态添加自定义词汇
        List<Term> termList = segment.seg(str);
        for (Term term : termList) {
            str1.add(term.toString());
        }
        if (str1.size() == 0) {
            return null;
        }
        return str1;
    }

    public static double getSimilarity(Vector<String> T1, Vector<String> T2) throws Exception {
        int size = 0, size2 = 0;
        if (T1 != null && (size = T1.size()) > 0 && T2 != null && (size2 = T2.size()) > 0) {

            Map<String, double[]> T = new HashMap<String, double[]>();
            String index = null;
            for (int i = 0; i < size; i++) {
                index = T1.get(i);
                if (index != null) {
                    double[] c = T.get(index);
                    c = new double[2];
                    c[0] = 1;    //T1的语义分数Ci
                    c[1] = 0.2;//T2的语义分数Ci
                    T.put(index, c);
                }
            }
            for (int i = 0; i < size2; i++) {
                index = T2.get(i);
                if (index != null) {
                    double[] c = T.get(index);
                    if (c != null && c.length == 2) {
                        c[1] = 1; //T2中也存在，T2的语义分数=1
                    } else {
                        c = new double[2];
                        c[0] = 0.2; //T1的语义分数Ci
                        c[1] = 1; //T2的语义分数Ci
                        T.put(index, c);
                    }
                }
            }
            //开始计算，百分比
            Iterator<String> it = T.keySet().iterator();
            double s1 = 0, s2 = 0, Ssum = 0;  //S1、S2
            while (it.hasNext()) {
                double[] c = T.get(it.next());
                Ssum += c[0] * c[1];
                s1 += c[0] * c[0];
                s2 += c[1] * c[1];
            }
            //百分比
            return Ssum / Math.sqrt(s1 * s2);
        } else {
            throw new Exception("传入参数有问题！");
        }
    }

    @Override
    public Map<String, String> detailBookByISBN(BookDetails bookDetails) {
        List<Book> books = bookDetailMapper.searchByMessage(bookDetails);
        Map<String, String> map = new HashMap<>();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        map.put("ISBN", books.get(0).getISBN());
        map.put("book_name", books.get(0).getBookName());
        map.put("publisher", books.get(0).getPublisher());
        map.put("published_time", simpleDateFormat.format(books.get(0).getPublishedTime()));
        map.put("author", books.get(0).getAuthor());
        map.put("cover", books.get(0).getCover());
        map.put("category", books.get(0).getCategory());
        return map;
    }

    @Override
    public ArrayList<Map<String, String>> searchBookLocationByISBN(String ISBN) {
        List<BookLocation> locations = bookDetailMapper.searchBookLocationByISBN(ISBN);
        ArrayList<Map<String, String>> maps = new ArrayList<>();
        for (BookLocation location :
                locations) {
            Map<String, String> map = new HashMap<>();
            map.put("book_id", location.getBookId());
            map.put("status", location.getStatus());
            map.put("room_number", location.getRoomNumber());
            map.put("book_shelf", location.getBookShelf());
            map.put("side", location.getSide());
            map.put("layer", location.getLayer());
            maps.add(map);
        }
        return maps;
    }


}
